#include "InStreamWrapper.h"


namespace SevenZip
{
namespace intl
{

	InStreamWrapper::InStreamWrapper( const CMyComPtr< IStream >& baseStream )
		: m_refCount( 0 )
		, m_baseStream( baseStream )
	{
	}

	InStreamWrapper::~InStreamWrapper()
	{
	}

	HRESULT STDMETHODCALLTYPE InStreamWrapper::QueryInterface( REFIID iid, void** ppvObject )
	{ 
		if ( iid == __uuidof( IUnknown ) )
		{
			*ppvObject = reinterpret_cast< IUnknown* >( this );
			AddRef();
			return S_OK;
		}

		if ( iid == IID_ISequentialInStream )
		{
			*ppvObject = static_cast< ISequentialInStream* >( this );
			AddRef();
			return S_OK;
		}

		if ( iid == IID_IInStream )
		{
			*ppvObject = static_cast< IInStream* >( this );
			AddRef();
			return S_OK;
		}

		if ( iid == IID_IStreamGetSize )
		{
			*ppvObject = static_cast< IStreamGetSize* >( this );
			AddRef();
			return S_OK;
		}

		return E_NOINTERFACE;
	}

	ULONG STDMETHODCALLTYPE InStreamWrapper::AddRef()
	{
		return static_cast< ULONG >( InterlockedIncrement( &m_refCount ) );
	}

	ULONG STDMETHODCALLTYPE InStreamWrapper::Release()
	{
		ULONG res = static_cast< ULONG >( InterlockedDecrement( &m_refCount ) );
		if ( res == 0 )
		{
			delete this;
		}
		return res;
	}

	STDMETHODIMP InStreamWrapper::Read( void* data, UInt32 size, UInt32* processedSize )
	{
		ULONG read = 0;
		HRESULT hr = m_baseStream->Read( data, size, &read );
		if ( processedSize != NULL )
		{
			*processedSize = read;
		}
		// Transform S_FALSE to S_OK
		return SUCCEEDED( hr ) ? S_OK : hr;
	}

	STDMETHODIMP InStreamWrapper::Seek( Int64 offset, UInt32 seekOrigin, UInt64* newPosition )
	{
		LARGE_INTEGER move;
		ULARGE_INTEGER newPos;

		move.QuadPart = offset;
		HRESULT hr = m_baseStream->Seek( move, seekOrigin, &newPos );
		if ( newPosition != NULL )
		{
			*newPosition =  newPos.QuadPart;
		}
		return hr;
	}

	STDMETHODIMP InStreamWrapper::GetSize( UInt64* size )
	{
		STATSTG statInfo;
		HRESULT hr = m_baseStream->Stat( &statInfo, STATFLAG_NONAME );
		if ( SUCCEEDED( hr ) )
		{
			*size = statInfo.cbSize.QuadPart;
		}
		return hr;
	}

}
}
